# 工具输入模式

默认情况下，工具通过检查函数签名来推断参数模式。为了更严格的要求，可以指定自定义输入模式，以及自定义验证逻辑。

```python
from typing import Any, Dict

from langchain.agents import AgentType, initialize_agent
from langchain.llms import OpenAI
from langchain.tools.requests.tool import RequestsGetTool, TextRequestsWrapper
from pydantic import BaseModel, Field, root_validator
``` 

以上代码导入了一些需要用到的库和模块。

```python
llm = OpenAI(temperature=0)
```

创建一个OpenAI对象，用于调用OpenAI的API。

```python
!pip install tldextract > /dev/null
```

安装`tldextract`库，用于从url中提取域名。

```python
[notice] A new release of pip is available: 23.0.1 -> 23.1
[notice] To update, run: pip install --upgrade pip
```

显示pip可升级的提示信息。

```python
import tldextract

_APPROVED_DOMAINS = {
    "langchain",
    "wikipedia",
}

class ToolInputSchema(BaseModel):

    url: str = Field(...)
    
    @root_validator
    def validate_query(cls, values: Dict[str, Any]) -> Dict:
        url = values["url"]
        domain = tldextract.extract(url).domain
        if domain not in _APPROVED_DOMAINS:
            raise
```

以上代码定义了一个工具输入模式，包含了url字段。使用`root_validator`装饰器定义了一个验证器，用于验证url是否属于指定的域名之一。

如果不属于，则抛出异常。`ValueError(f"域名 {domain} `不在批准列表中: `{sorted(_APPROVED_DOMAINS)}")`
    return values
    
```python
tool = RequestsGetTool(args_schema=ToolInputSchema, requests_wrapper=TextRequestsWrapper())

```










```python
agent = initialize_agent([tool], llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=False)

```










```python
# 这将成功，因为在验证期间不会触发任何参数
answer = agent.run("langchain.com 的主标题是什么？")
print(answer)

```








```python
langchain.com 的主标题是 "LANG CHAIN 🦜️🔗 官方主页"

```










```python
agent.run("google.com 的主标题是什么？")

```








```python

ValidationError Traceback (most recent call last)
Cell In[7], line 1
----> 1 agent.run("google.com 的主标题是什么？")

File ~/code/lc/lckg/langchain/chains/base.py:213, in Chain.run(self, \*args```python

``` 

```python
在文件~/code/lc/lckg/langchain/chains/base.py中的116行，Chain的__call__方法抛出异常。在113行，该方法调用_call方法，并在try语句中捕获异常。在110行到111行之间，Chain的callback_manager管理器的on_chain_start方法被调用，传递了Chain的名称和输入参数。如果kwargs存在且args不存在，则在215行返回self(kwargs)[self.output_keys[0]]。如果args存在且长度不等于1，则在212行引发ValueError异常。否则，在213行返回self(args[0])[self.output_keys[0]]。如果try语句块内抛出异常，则在115行调用Chain的callback_manager管理器的on_chain_error方法，并重新抛出异常。在118行，Chain的callback_manager管理器的on_chain_end方法被调用，传递了输出参数和verbose参数。最后，在119行返回prep_outputs方法的结果，该方法接收输入参数、输出参数和return_only_outputs参数。在文件~/code/lc/lckg/langchain/agents/agent.py的第792行，当出现链错误时，调用back_manager.on_chain_error(e, verbose=self.verbose)函数。

在文件~/code/lc/lckg/langchain/agents/agent.py的第790行，进入Agent循环，直到返回某些东西。

在AgentExecutor._call(self, inputs)函数中，第792行调用了_take_next_step()函数，该函数传入name_to_tool_map、color_mapping、inputs和intermediate_steps参数。

在AgentExecutor._take_next_step(self, name_to_tool_map, color_mapping, inputs, intermediate_steps)函数中，第695行调用了tool.run()函数，传入agent_action.tool_input、verbose=self.verbose、color和tool_run_kwargs等参数，以获取观察值。如果agent_action是None，则返回None。在文件~/code/lc/lckg/langchain/tools/base.py的第110行，BaseTool类的run方法中，获取了self.agent.tool_run_logging_kwargs()的参数并赋值给tool_run_kwargs。

在文件~/code/lc/lckg/langchain/tools/base.py的第71行，BaseTool类的_parse_input方法中，解析了tool_input，并将其返回。

在文件~/code/lc/lckg/.venv/lib/python3.11/site-packages/pydantic/main.py的第526行，BaseModel类的parse_obj方法被调用。在/pydantic/main.py的第341行，pydantic.main.BaseModel.__init__()函数的参数校验出错了，错误信息是：ToolInputSchema的__root__字段的值不在['langchain', 'wikipedia']中，不符合要求。

```  python